#include "bs_cl.h"
#include "hr_time.h"

//#define DEBUG 

#ifdef DEBUG
void print_arr(BS_test_t * t, cl_float *arr);
#endif

double launch_BS(BS_test_t *t)
{
		CStopWatch tim;

		size_t szLocalWorkSize[1];
		size_t szGlobalWorkSize[1];
		cl_int errcode_ret;
		
		szLocalWorkSize[0] = t->blockSize;
		szGlobalWorkSize[0] = t->gridSize;

		// setup parameter values 
		errcode_ret = clSetKernelArg(t->hBSKernel, 0, sizeof(cl_mem),   (void *)&t->d_CallResult);
		ERR_CHECK(errcode_ret, "clSetKernelArg");
		errcode_ret = clSetKernelArg(t->hBSKernel, 1, sizeof(cl_mem),   (void *)&t->d_PutResult);
		ERR_CHECK(errcode_ret, "clSetKernelArg");
		errcode_ret = clSetKernelArg(t->hBSKernel, 2, sizeof(cl_mem),   (void *)&t->d_StockPrice);
		ERR_CHECK(errcode_ret, "clSetKernelArg");
		errcode_ret = clSetKernelArg(t->hBSKernel, 3, sizeof(cl_mem),   (void *)&t->d_OptionStrike);
		ERR_CHECK(errcode_ret, "clSetKernelArg");
		errcode_ret = clSetKernelArg(t->hBSKernel, 4, sizeof(cl_mem),   (void *)&t->d_OptionYears);
		ERR_CHECK(errcode_ret, "clSetKernelArg");
		errcode_ret = clSetKernelArg(t->hBSKernel, 5, sizeof(cl_float), (void *)&t->Riskfree);
		ERR_CHECK(errcode_ret, "clSetKernelArg");
		errcode_ret = clSetKernelArg(t->hBSKernel, 6, sizeof(cl_float), (void *)&t->Volatility);
		ERR_CHECK(errcode_ret, "clSetKernelArg");
		errcode_ret = clSetKernelArg(t->hBSKernel, 7, sizeof(cl_uint),  (void *)&t->num);
		ERR_CHECK(errcode_ret, "clSetKernelArg");

		printf("starting %d iterations...\n", t->run_num_iters);
		tim.startTimer();
		
		for (int i = 0; i < t->run_num_iters; i++) {
			errcode_ret = clEnqueueNDRangeKernel(t->hCmdQueue, t->hBSKernel, 1, NULL, szGlobalWorkSize, szLocalWorkSize,
				0, NULL, NULL);
			ERR_CHECK(errcode_ret, "clEnqueueNDRangeKernel");

			clFlush(t->hCmdQueue);
			clFinish(t->hCmdQueue);
		}
		tim.stopTimer();

		return tim.getElapsedTime();
}
